Skip to content

Conversation

@runcom
Copy link
Member

@runcom runcom commented Nov 2, 2016

@mtrmac PTAL

More information available at moby/moby#27961

Signed-off-by: Antonio Murdaca [email protected]

@runcom runcom force-pushed the layers-federation branch from a387cea to f27ff17 Compare November 2, 2016 10:03
@runcom runcom changed the title *: support layers federation [WIP] *: support layers federation Nov 2, 2016
@runcom
Copy link
Member Author

runcom commented Nov 2, 2016

@mtrmac I just like to understand how you feel about this, I know the code is broken and need a look of fixing around "UpdatedImage" and such

Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, well, if it is a needed feature supported by docker/distribution, we will need to support it, so what’s not to like?

I would, however, like to see a comprehensive documentation somewhere of what this is supposed to do and why and how. Right now this adds URLs without any documentation; is the semantics that these layers should not or must not be copied? Will they always be accessible without authentication? (Perhaps these things are already documented somewhere in docker/distribution?)

And it might be desirable to have tests for schema conversion before this lands, and tests for how schema conversion interacts with this, and perhaps also tests for interaction with containers/storage. This kind of change seems somewhat likely to break something without us noticing.

copy/copy.go Outdated
}
cl = copiedLayer{blobInfo: destInfo, diffID: diffID}
} else {
fmt.Fprintf(reportWriter, "Skipping foreign layer copy to %s\n", dest.Reference().Transport().Name())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to fill in info for manifestUpdates.{InformationOnly.,}LayerInfos and possibly for manifestUpdates.InformationOnly.LayerDiffIDs which is much more horrible.

Also we might want to record URLs for the newly created layers as well.

copy/copy.go Outdated
err error
)
for _, url := range srcInfo.URLs {
resp, err = http.Get(url)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing a specific transport like this in the generic copy code is weird. Why wouldn’t this be done by an ImageSource, perhaps through ImageSource.GetBlob(info types.BlobInfo)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular, does the access never need any authentication?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In particular, does the access never need any authentication?

answer to this is, sadly, we don't yet know, ongoing discussion at moby/moby#27961

Implementing a specific transport like this in the generic copy code is weird. Why wouldn’t this be done by an ImageSource, perhaps through ImageSource.GetBlob(info types.BlobInfo)?

makes sense

// uploaded to the image destination, false otherwise.
func (d *ociImageDestination) CopyForeignLayers() bool {
return false
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this true for dir: but false for oci:? At a first glance it seems that the two should behave similarly.

types/types.go Outdated

// CopyForeignLayers returns true iff foreign layers in manifest should be actually
// uploaded to the image destination, false otherwise.
CopyForeignLayers() bool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps ShouldCopyForeignLayers or SupportsForeignLayers or something; this reads like a command to copy them.

@runcom runcom force-pushed the layers-federation branch 5 times, most recently from 1f99fdc to 1bcf590 Compare November 15, 2016 10:01
@runcom
Copy link
Member Author

runcom commented Nov 15, 2016

I would, however, like to see a comprehensive documentation somewhere of what this is supposed to do and why and how. Right now this adds URLs without any documentation; is the semantics that these layers should not or must not be copied? Will they always be accessible without authentication? (Perhaps these things are already documented somewhere in docker/distribution?)

moby/moby#27961

@mtrmac PTAL (skopeo PR containers/skopeo#249)

err error
)
for _, url := range urls {
resp, err = http.Get(url)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use the previously setup docker client to comply with containers/skopeo#250

@runcom runcom force-pushed the layers-federation branch 2 times, most recently from f4bb04e to 488f068 Compare November 23, 2016 16:50
@runcom
Copy link
Member Author

runcom commented Nov 23, 2016

ping @mtrmac anything else?

@runcom
Copy link
Member Author

runcom commented Nov 25, 2016

rebased

Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The highlights are authentication and the naming vs. semantics of SupportsForeignLayers.

Also, shouldn’t convertToManifestSchema1 refuse to convert images with federated URLs?

return nil, fmt.Errorf("Internal error: neither src nor configBlob set in manifestSchema2")
}
stream, _, err := m.src.GetBlob(m.ConfigDescriptor.Digest)
stream, _, err := m.src.GetBlob(types.BlobInfo{Digest: m.ConfigDescriptor.Digest})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn’t this fully convert the descriptor, including URLs?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the very least, Size should be -1, not 0.

GetTargetManifest(digest string) ([]byte, string, error)
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
GetBlob(digest string) (io.ReadCloser, int64, error)
GetBlob(BlobInfo) (io.ReadCloser, int64, error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the caller expected to fill in everything, in particular is Size required?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(AFAICT we don’t need it, so this would be just a matter of documenting The Digest field is guaranteed to be provided; Size may be -1 just as we do for LayerInfos where this information comes from.)

return nil, 0, err
}

func getBlobSizeFromHeader(h string) int64 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could get a http.Response and look up the Content-Length header itself. This works as well, but the FromHeader naming is a bit confusing, when this is just a decimal parser.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Also there is another parser of Content-Length in docker_image_dest.go which could be modified to call this.)

err error
)
for _, url := range urls {
resp, err = s.c.makeRequestToResolvedURL("GET", url, nil, nil, -1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I asked about authentication; still, is this right?

This would, when pulling a foreign RHEL from docker.io, send the docker.io credentials to Red Hat.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, we just need the client w/o auth here because we may need auth certificates against the give foreign server. We may probably need a new method in the client to make calls w/o authentication but still honor cert-path and the like for the given server we're connecting to here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, using the certs but not sending any tokens/passwords is AFAICT safe.

Ultimately, we would need to decide where the tokens/passwords are configured, and whether that is a per-transport matter or something general, and so on, but if we don’t have any server needing this right now, let's get this merged first and worry about that later.

copy/copy.go Outdated
func copyLayer(dest types.ImageDestination, src types.ImageSource, srcInfo types.BlobInfo,
diffIDIsNeeded bool, canCompress bool, reportWriter io.Writer) (types.BlobInfo, string, error) {
srcStream, srcBlobSize, err := src.GetBlob(srcInfo.Digest) // We currently completely ignore srcInfo.Size throughout.
srcStream, srcBlobSize, err := src.GetBlob(srcInfo) // We currently completely ignore srcInfo.Size throughout.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the srcInfo.Size comment still accurate? (See also types.go)

copy/copy.go Outdated
)
if !dest.SupportsForeignLayers() && len(srcLayer.URLs) != 0 {
destInfo = srcLayer
// TODO: diffID?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it happens, DiffIDs are, at least currently, needed only when converting from schema1, in which case src.LayerInfos will not have URLs because schema1 does not support them. So, luckily enough, we don’t need to be handling this; just add a check

if diffIDsAreNeeded {
   return errors.New("getting DiffIDs for foreign layers is unimplemented") // and a comment explaining schema1
}

copy/copy.go Outdated
if !dest.SupportsForeignLayers() && len(srcLayer.URLs) != 0 {
destInfo = srcLayer
// TODO: diffID?
fmt.Fprintf(reportWriter, "Skipping foreign layer copy to %s\n", dest.Reference().Transport().Name())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably identify the blob by digest (and the Copying Blob message above should go into the else branch below).

types/types.go Outdated

// SupportsForeignLayers returns true iff foreign layers in manifest should be actually
// uploaded to the image destination, false otherwise.
SupportsForeignLayers() bool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This naming is pretty confusing; this should return false exactly in the cases when the destination understands URLs.

As is, this is really ShouldConvertForeignLayersToBlobCopies :) Or perhaps keep the current semantics and call it AcceptsForeignLayerURLs?

if len(l.URLs) != 0 {
om.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable
} else {
om.Layers[i].MediaType = imgspecv1.MediaTypeImageLayer
Copy link
Collaborator

@mtrmac mtrmac Nov 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly the OCI discussion of URLs vs. MIME types, URLs means “pull from here” and a MIME type can be used to indicate “don’t push this”; if so, the OCI MIME type should be based on whether the Docker MIME type is a …rootfs.foreign.diff…, not on the presence of URLs.

Or is the semantics of URLs vs. MIME type different between Docker s2 and OCI?

@runcom
Copy link
Member Author

runcom commented Nov 26, 2016

@mtrmac updated and fixed your comments. PTAL

@runcom
Copy link
Member Author

runcom commented Nov 28, 2016

rebased again.


// AcceptsForeignLayerURLs returns true iff foreign layers in manifest should be actually
// uploaded to the image destination, false otherwise.
AcceptsForeignLayerURLs() bool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m sorry, I have suggested this exact wording and this is entirely my fault, but AcceptsForeignLayerURLs is the opposite of what the flag means: false = keep the BlobInfo with the URL, true = make a copy.

(Writing this out in case I am making another mistake.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I rework the comment here and swap true with false then right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@runcom
Copy link
Member Author

runcom commented Nov 30, 2016

@mtrmac updated and rebased

@mtrmac
Copy link
Collaborator

mtrmac commented Nov 30, 2016

I still see AcceptsForeignLayerURLs false for docker:/atomic:, and false causing the URLs to be preserved, i.e. no change ?!

@runcom
Copy link
Member Author

runcom commented Nov 30, 2016

I still see AcceptsForeignLayerURLs false for docker:/atomic:, and false causing the URLs to be preserved, i.e. no change ?!

How about now? I swapped all occurrences I guess

@mtrmac
Copy link
Collaborator

mtrmac commented Nov 30, 2016

Missing the use in copy.go AFAICS

@runcom
Copy link
Member Author

runcom commented Nov 30, 2016

Missing the use in copy.go AFAICS

yep, sorry, forget me, I updated the use in copy as well.

@mtrmac
Copy link
Collaborator

mtrmac commented Nov 30, 2016

👍

Thanks!

Approved with PullApprove

@runcom
Copy link
Member Author

runcom commented Nov 30, 2016

lgtm

thanks @mtrmac sorry for the back and forth

Approved with PullApprove

@runcom
Copy link
Member Author

runcom commented Nov 30, 2016

I'll fix the skopeo PR before merging here, stay tuned

Signed-off-by: Antonio Murdaca <[email protected]>
@runcom
Copy link
Member Author

runcom commented Nov 30, 2016

containers/skopeo#249 is good to go as well, merging here

@runcom runcom merged commit 3040b28 into containers:master Nov 30, 2016
@runcom runcom deleted the layers-federation branch November 30, 2016 18:47
giuseppe pushed a commit to giuseppe/image that referenced this pull request Jan 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants